<?php

namespace App\Services;

use App\Common\Helpers\Functions;
use App\Common\Services\BaseService;
use App\Common\Services\SystemApi\CenterApiService;
use App\Common\Tools\CustomException;
use App\Common\Tools\CustomLock;
use App\Enums\NoticeWayEnums;
use App\Enums\SendStatusEnums;
use App\Jobs\SendMessageJob;
use App\Models\MessageModel;

class MessageService extends BaseService
{
    /**
     * constructor.
     */
    public function __construct(){
        parent::__construct();

        $this->model = new MessageModel();
    }

    /**
     * @param $data
     * @param $noticeWay
     * @return bool
     * @throws CustomException
     * 创建
     */
    public function create($data, $noticeWay){
        $this->validRule($data, [
            'title' => 'required',
            'content' => 'required',
            'admin_ids' => 'required|array',
        ]);

        Functions::hasEnum(NoticeWayEnums::class, $noticeWay);

        // 获取用户信息映射
        $centerApiService = new CenterApiService();
        $adminUsers = $centerApiService->apiGetAdminUsers();
        $adminUserMap = array_column($adminUsers, null, 'id');

        $extendsMap = [];
        if($noticeWay == NoticeWayEnums::FEISHU){
            $names = [];
            foreach($data['admin_ids'] as $adminId){
                $names[] = $adminUserMap[$adminId]['name'] ?? '';
            }

            $feishuService = new FeishuService();
            $employees = $feishuService->getEmployees();

            // 员工名称
            $employeeNames = $employees->pluck('name');

            // 未知员工
            $notFoundNames = [];
            foreach($names as $name){
                if(!in_array($name, $employeeNames->toArray())){
                    $notFoundNames[] = $name;
                }
            }

            if(!empty($notFoundNames)){
                throw new CustomException([
                    'code' => 'NOT_FOUND_EMPLOYEE_NAMES',
                    'message' => "存在未知管理员名称",
                    'data' => [
                        'not_found_employee_names' => $notFoundNames,
                    ],
                ]);
            }

            // 扩展字段
            foreach($data['admin_ids'] as $adminId){
                $extendsMap[$adminId] = [
                    'admin_user_name' => $adminUserMap[$adminId]['name'] ?? '',
                ];
            }
        }elseif($noticeWay == NoticeWayEnums::ALISMS){
            // 未绑定手机用户名
            $unBindPhoneNames = [];
            foreach($data['admin_ids'] as $adminId){
                $phone = $adminUserMap[$adminId]['phone'] ?? '';
                if(empty($phone)){
                    $unBindPhoneNames[] = $adminUserMap[$adminId]['name'];
                }
            }

            if(!empty($unBindPhoneNames)){
                throw new CustomException([
                    'code' => 'UN_BIND_PHONE_NAMES',
                    'message' => "存在用户未绑定手机号",
                    'data' => [
                        'un_bind_phone_names' => $unBindPhoneNames,
                    ],
                ]);
            }

            foreach($data['admin_ids'] as $adminId){
                $extendsMap[$adminId] = [
                    'admin_user_phone' => $adminUserMap[$adminId]['phone'] ?? '',
                ];
            }
        }

        // 锁
        if(!empty($data['lock_time'])){
            // 签名
            $sign = md5(json_encode($data['content']));

            $key = 'message_create:'. $sign;
            $lock = new CustomLock($key);

            if($lock->isLock()){
                return true;
            }

            $lockTime = intval($data['lock_time']);
            $lock->set($lockTime);
        }

        foreach($data['admin_ids'] as $adminId){
            $this->model->title = $data['title'];
            $this->model->content = $data['content'];
            $this->model->admin_id = $adminId;
            $this->model->notice_way = $noticeWay;
            $this->model->send_status = SendStatusEnums::WAITING;
            $this->model->extends = $extendsMap[$adminId] ?? [];
            $ret = $this->model->save();

            if($ret){
                // 创建发送消息任务
                dispatch(new SendMessageJob($this->model));
            }
        }

        return true;
    }

    /**
     * @param $message
     * @throws CustomException
     * 发送
     */
    public function send($message){
        $extends = [];
        if($message->notice_way == NoticeWayEnums::FEISHU){
            // 内容转数组
            $rows = $this->contentToArray($message->content);

            $tags = [];
            foreach($rows as $row){
                // 构建文本标签
                $tags[] = $this->buildTextTag($row);
            }

            // 发送消息
            $feishuService = new FeishuService();
            $data = $feishuService->sendMessage($message->extends->admin_user_name, $message->title, $tags);

            // 扩展字段
            $extends = [
                'feishu_message_id' => $data['message_id'] ?? '',
            ];
        }elseif($message->notice_way == NoticeWayEnums::ALISMS){
            $aliService = new AliService();
            $data = $aliService->sendSmsCaptcha($message->extends->admin_user_phone, $message->content);

            // 扩展字段
            $extends = [
                'ali_sms_request_id' => $data['RequestId'] ?? '',
                'ali_sms_biz_id' => $data['BizId'] ?? '',
            ];
        }

        $message->extends = (object) array_merge((array) $message->extends, $extends);
        $message->send_status = SendStatusEnums::SUCCESS;
        $message->save();
    }

    /**
     * @param $content
     * @return array
     * 内容转数组
     */
    public function contentToArray($content){
        // 兼容
        $content = str_replace(['</br>', '<br/>'],'<br>',$content);

        // 分割
        $rows = explode("<br>", $content);

        return $rows;
    }

    /**
     * @param $string
     * @return string|string[]|null
     * 构建文本标签
     */
    public function buildTextTag($string){
        preg_match_all("/<.+?>(.*?)<\/.+?>/", $string, $m);

        $expStr = preg_replace("/<.+?>(.*?)<\/.+?>/", '#explode#', $string);

        $texts = explode("#explode#", $expStr);

        $tagTexts = array_map(function($value){
            return "<text>{$value}</text>";
        }, $texts);

        $string = implode("#explode#", $tagTexts);

        foreach($m[0] as $k => $v){
            $string = preg_replace("/#explode#/", $v, $string, 1);
        }

        return $string;
    }
}
